#ifndef MODULES_CORE_EVENT_H_
#define MODULES_CORE_EVENT_H_

enum EVENT_KEY {
	EVENT_WIFI_CONNECTED, EVENT_WIFI_CLOSE, EVENT_SERIAL_MESSAGE, EVENT_DECODE_MESSAGE, _EVENT_END,
};
enum CMD_KEY {
	TEST1, TEST2, MINI_MP3,_CMD_END,
};
/**
 * cmd模式解码注册
 * **/
#define cmd_injection_handle(m,fn,arg,type) \
	void fn(arg);\
 	void fn(TaskCtx<type*> * ctx){\
		fn(ctx->ctx);\
	}\
	void fn(std::string json){\
 		type* obj = new type;\
 		JsonHelper::JsonToObject(*obj,json);\
 		TaskCtx<type*> * ctx =  new TaskCtx<type*>(obj);\
 		EventService::trigger(EVENT_DECODE_MESSAGE, ctx);\
 	}\
	__attribute__((constructor)) void __##fn##__(){\
 		GET_BEAN(MODEL_CMD,CmdService)->registerHandle(m,&fn);\
 		EventService::registerHandle(EVENT_DECODE_MESSAGE,&fn);\
	}\
	void fn(arg)

/**
 * 事件注册
 * */
#define event_injection_handle(m,fn,arg) \
	void fn(arg);\
	__attribute__((constructor)) void __##fn##__(){\
		EventService::registerHandle(m,&fn);\
	}\
	void fn(arg)

template<typename T>
void deleteIfPtr(T *ptr) {
	if (ptr == nullptr) {
		return;
	}
	delete ptr;
}

template<typename T>
void deleteIfPtr(T v) { /* else, do nothing */
}

template<typename T>
class TaskCtx {
private:
	std::atomic<uint16_t> taskSize;
	bool delCtx = true;

public:
	T ctx;
	uint8_t cpu=-1;
	/***
	 * @param delCtx 执行执行完后 自动删除 ctx 如 new TaskCtx<TestTaskDel*>(new TestTaskDel,true);
	 * @param ctx taskSize 执行执行完后-1 为0时自动删除 TaskCtx
	 * */
	TaskCtx<T>(T ctx, uint8_t cpu=-1,bool delCtx = true, uint16_t taskSize = 1) :
					ctx(ctx),  cpu(cpu),delCtx(delCtx), taskSize(taskSize) {
	}
	void initTaskSize(uint16_t taskSize) {
		this->taskSize = taskSize;
	}
	void decAndGc() {
		this->taskSize--;
		if (this->taskSize > 0) {
			return;
		}
		gc();
	}
	void gc() {
		if (this->delCtx) {
			//模板 基本类型不能 delete 用多态方法解决
			deleteIfPtr(this->ctx);
		}
		delete this;
	}
};

//https://www.cnblogs.com/flysong/articles/10047700.html
template<typename T>
//模板必须要用 using....
using TaskFunction = void(*)(TaskCtx<T>*);

#endif /* MODULES_CORE_EVENT_H_ */
